try retrieval from more than one export location when the first fails
authorJoey Hess <joeyh@joeyh.name>
Tue, 20 Sep 2022 17:33:57 +0000 (13:33 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 20 Sep 2022 17:33:57 +0000 (13:33 -0400)
Combined with commit 0ffc59d34107a3ee671b90fc7c59ca09c00abbf5, this
fixes the case where there are duplicate files on the special remote,
and the first gets modified/deleted, while the second is still present.

directory, adb: Fixed a bug when importtree=yes, and multiple files in the
special remote have the same content, that caused it to refuse to get a
file from the special remote, incorrectly complaining that it had changed,
due to only accepting the inode+mtime of one file (that was since modified
or deleted) and not accepting the inode+mtime of other duplicate files.

Sponsored-by: Max Thoursie on Patreon
CHANGELOG
Remote/Helper/ExportImport.hs

index 6c6f009293735478965c5666b2633a03fdab3e1a..c054007290bc6d2c73576eb9a1e44d7c77dedb82 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,12 @@ git-annex (10.20220823) UNRELEASED; urgency=medium
     ignoreinode setting has been changed. When getting a file from such a
     remote, accept the content that would have been accepted with the
     previous ignoreinode setting.
+  * directory, adb: Fixed a bug when importtree=yes, and multiple files
+    in the special remote have the same content, that caused it to
+    refuse to get a file from the special remote, incorrectly complaining
+    that it had changed, due to only accepting the inode+mtime of one file
+    (that was since modified or deleted) and not accepting the inode+mtime
+    of other duplicate files.
 
  -- Joey Hess <id@joeyh.name>  Mon, 29 Aug 2022 15:03:04 -0400
 
index ddccda74dd8f3b2d78b3ace5e221af3814312ccc..1d71ae70d110e423ae4ba63d8336ebe7212e3829 100644 (file)
@@ -327,11 +327,6 @@ adjustExportImport' isexport isimport r rs = do
                db <- getexportdb dbv
                liftIO $ Export.getExportTree db k
        
-       getfirstexportloc dbv k = do
-               getexportlocs dbv k >>= \case
-                       [] -> giveup "unknown export location"
-                       (l:_) -> return l
-       
        getexportlocs dbv k = do
                db <- getexportdb dbv
                liftIO $ Export.getExportTree db k >>= \case
@@ -340,6 +335,15 @@ adjustExportImport' isexport isimport r rs = do
                                , return []
                                )
                        ls -> return ls
+       
+       tryexportlocs dbv k a = 
+               go Nothing =<< getexportlocs dbv k
+         where
+               go Nothing [] = giveup "unknown export location"
+               go (Just ex) [] = throwM ex
+               go _ (l:ls) = tryNonAsync (a l) >>= \case
+                       Right v -> return v
+                       Left e -> go (Just e) ls
                
        getkeycids ciddbv k = do
                db <- getciddb ciddbv
@@ -350,9 +354,8 @@ adjustExportImport' isexport isimport r rs = do
        -- have replaced with content not of the requested key, the content
        -- has to be strongly verified.
        retrieveKeyFileFromExport dbv k _af dest p = ifM (isVerifiable k)
-               ( do
-                       l <- getfirstexportloc dbv k
-                       retrieveExport (exportActions r) k l dest p >>= return . \case
+               ( tryexportlocs dbv k $ \loc -> 
+                       retrieveExport (exportActions r) k loc dest p >>= return . \case
                                UnVerified -> MustVerify
                                IncompleteVerify iv -> MustFinishIncompleteVerify iv
                                v -> v
@@ -362,9 +365,8 @@ adjustExportImport' isexport isimport r rs = do
        retrieveKeyFileFromImport dbv ciddbv k af dest p = do
                cids <- getkeycids ciddbv k
                if not (null cids)
-                       then do
-                               l <- getfirstexportloc dbv k
-                               snd <$> retrieveExportWithContentIdentifier (importActions r) l cids dest (Left k) p
+                       then tryexportlocs dbv k $ \loc ->
+                               snd <$> retrieveExportWithContentIdentifier (importActions r) loc cids dest (Left k) p
                        -- In case a content identifier is somehow missing,
                        -- try this instead.
                        else if isexport